package io.kiki.sba.registry.remoting.netty;


import io.kiki.sba.registry.api.ChannelHandler;
import io.kiki.sba.registry.util.StringFormatter;
import io.kiki.stack.netty.channelManager.ChannelEventProcessor;
import io.kiki.stack.netty.channelManager.ChannelEventType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class ChannelEventProcessorImpl implements ChannelEventProcessor {

    private static final Logger logger = LoggerFactory.getLogger(ChannelEventProcessorImpl.class);

    private final ChannelEventType channelEventType;

    private final ChannelHandler channelHandler;


    public ChannelEventProcessorImpl(ChannelEventType channelEventType, ChannelHandler channelHandler) {
        this.channelEventType = channelEventType;
        // the connect event handler maybe is null
        this.channelHandler = channelHandler;
    }


    @Override
    public void onEvent(io.kiki.stack.netty.channelManager.Channel channel, String remoteAddr) {
        try {
            switch (channelEventType) {
            case CONNECT:
                if (channelHandler != null) {
                    channelHandler.connected(new Channel(channel));
                }
                logger.info("[connect]local={},remote={}", channel.getLocalPort(), remoteAddr);
                break;

            case CLOSE:
                if (channelHandler != null) {
                    channelHandler.disconnected(new Channel(channel));
                }
                logger.info("[close]local={},remote={}", channel.getLocalPort(), remoteAddr);
                break;

            case EXCEPTION:
                if (channelHandler != null) {
                    channelHandler.exceptionCaught(new Channel(channel), null, null);
                }
                logger.error("[exception]local={},remote={}", channel.getLocalPort(), remoteAddr);
                break;
            case CONNECT_FAILED:
                logger.error("[connectFailed]local={},remote={}", channel.getLocalPort(), remoteAddr);
                break;
            default:
                break;
            }
        } catch (Throwable e) {
            String err = StringFormatter.format("failed to process connection, type={}, local={}, remote={}, conn={}", channelEventType, channel.getLocalPort(), remoteAddr, channel);
            logger.error(err, e);
            throw new RuntimeException(err, e);
        }
    }
}
